package com.binfenhulian.chinaenergy.ces.manage.core.oss.service;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PolicyConditions;
import com.binfenhulian.chinaenergy.ces.utils.random.RandomGUIDUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.time.LocalDate;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by wanghjbuf on 2018/3/19.
 */
@Slf4j
@Service("com.binfenhulian.chinaenergy.ces.manage.core.oss.service.OSSServiceImpl")
public class OSSServiceImpl implements OSSService{

    @Value("${oss.host}")
    private String endpoint;
    @Value("${oss.policy.host}")
    private String policyEndpoint;
    @Value("${oss.fileHost}")
    private String fileHost;
    @Value("${oss.accessKeyId}")
    private String accessKeyId;
    @Value("${oss.accessKeySecret}")
    private String accessKeySecret;
    @Value("${oss.bucketName}")
    private String bucketName;
    @Resource(name = "defRedisTemplate")
    RedisTemplate<String, Object> redisTemplate;

    private static final String CachePrefix = "OssTempUrlMap:";

    @Override
    public String upLoadFile(String key, byte[] bytes) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(bytes));
        ossClient.shutdown();
        return key;
    }

    @Override
    public String upLoadFile(byte[] bytes) {
        String key = RandomGUIDUtil.getRawGUID();
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(bytes));
        ossClient.shutdown();
        return key;
    }

    @Override
    public String upLoadFile(String dirStr, String fileStr, byte[] bytes) {
        LocalDate current = LocalDate.now();
        StringBuffer sb = new StringBuffer(dirStr).append("/").append(current.getYear()).append("/").append(current.getMonthValue()).append("/").append(current.getDayOfMonth()).append("/").append(fileStr);
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, sb.toString(), new ByteArrayInputStream(bytes));
        ossClient.shutdown();
        return sb.toString();
    }

    @Override
    public String getTempAccessUrl(String key) {
        String redisKey = CachePrefix + key;
        if (redisTemplate.hasKey(redisKey)) {
            String tmpUrl = (String) redisTemplate.opsForValue().get(redisKey);
            return tmpUrl;
        }
        Date expiration = new Date(System.currentTimeMillis() + 1000L * 3600 * 24);// 设置URL过期时间为24小时
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);// 生成URL
        String oriHost = url.getHost();
        String urlStr = url.toString().replace(oriHost, fileHost);

        redisTemplate.opsForValue().set(redisKey, urlStr, 60 * 59 * 24);//缓存到redis里 过期时间为1小时59分钟
        return urlStr;
    }

    @Override
    public String getTempAccessUrlForWithPub(String key) {
        String redisKey = CachePrefix + key;
        if (redisTemplate.hasKey(redisKey)) {
            String tmpUrl = (String) redisTemplate.opsForValue().get(redisKey);
            return tmpUrl;
        }
        Date expiration = new Date(System.currentTimeMillis() + 1000L * 3600 * 24);
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        String urlStr = url.toString().replace(url.getHost(), fileHost).split("\\?")[0];
        redisTemplate.opsForValue().set(redisKey, urlStr, 60 * 59 * 24);
        return urlStr;
    }

    @Override
    public byte[] getFile(String key) throws IOException {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        OSSObject ossObject = ossClient.getObject(bucketName, key);
        byte[] bytes = IOUtils.toByteArray(ossObject.getObjectContent());
        ossClient.shutdown();
        return bytes;
    }

    @Override
    public Map getPolicy() throws UnsupportedEncodingException {
        OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        String host = "http://" + bucketName + "." + policyEndpoint;
        long expireTime = 60 * 30;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);

        String postPolicy = client.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);

        Map<String, String> respMap = new LinkedHashMap<String, String>();
        respMap.put("accessid", accessKeyId);
        respMap.put("policy", encodedPolicy);
        respMap.put("signature", postSignature);
        respMap.put("host", host);
        respMap.put("expire", String.valueOf(expireEndTime / 1000));

        return JSONObject.fromObject(respMap);
    }
}
